package com.yunquan.ohana.ui.calendar.lists

import android.app.Application
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import androidx.databinding.ObservableArrayList
import androidx.databinding.ObservableField
import com.google.gson.Gson
import com.yunquan.ohana.BR
import com.yunquan.ohana.R
import com.yunquan.ohana.base.binding.command.BindingAction
import com.yunquan.ohana.base.binding.command.BindingCommand
import com.yunquan.ohana.base.binding.command.BindingConsumer
import com.yunquan.ohana.base.bus.RxBus
import com.yunquan.ohana.base.ui.AppManager
import com.yunquan.ohana.base.ui.BaseViewModel
import com.yunquan.ohana.db.DBFrames
import com.yunquan.ohana.dialog.LoadingDialog
import com.yunquan.ohana.entity.EventEntity
import com.yunquan.ohana.entity.EventType
import com.yunquan.ohana.entity.FramesDataManager
import com.yunquan.ohana.entity.FramesEntity
import com.yunquan.ohana.entity.ListsEntity
import com.yunquan.ohana.entity.LocalFrameEntity
import com.yunquan.ohana.http.BaseHttp
import com.yunquan.ohana.http.exception.ApiException
import com.yunquan.ohana.http.observer.BaseObserver
import com.yunquan.ohana.http.transformer.CommonTransformer
import com.yunquan.ohana.ui.calendar.event.week.dialog.BottomDeleteDialog
import com.yunquan.ohana.ui.calendar.lists.add.ListsAddActivity
import com.yunquan.ohana.utils.ToastUtils
import com.yunquan.ohana.utils.Utils
import io.reactivex.rxjava3.disposables.Disposable
import me.tatarka.bindingcollectionadapter2.ItemBinding
import okhttp3.RequestBody.Companion.toRequestBody

class ListsViewModel(application: Application) : BaseViewModel(application) {

    val isUserType = ObservableField<Boolean>()
    val isEdit = ObservableField(false)

    var mDeviceId: String? = null


    val items = ObservableArrayList<ListsItemViewModel>()
    val itemBinding = ItemBinding.of<ListsItemViewModel>(
        BR.listsItemViewModel,
        R.layout.item_lists_group,
    )

    val onAddListsClick = BindingCommand<Any>(object : BindingAction {
        override fun call() {
            val bundle = Bundle()
            bundle.putString("deviceId", mDeviceId)
            bundle.putBoolean("userType", isUserType.get() ?: false)
            startActivityResult(ListsAddActivity::class.java, bundle)
        }
    })

    val onCheckedChange = BindingCommand(object : BindingConsumer<Boolean> {
        override fun call(t: Boolean) {
            isEdit.set(t)
            items.forEach {
                it.isEdit.set(t)
            }
        }
    })

    val onDeleteClick = BindingCommand<Any>(object : BindingAction {
        override fun call() {
            val list = items.filter { it.checked.get() == true }.map { it.data }
            if (list.isNotEmpty()) {
                val deleteDialog = BottomDeleteDialog(AppManager.appManager.currentActivity()!!)
                deleteDialog.setTitle(
                    Utils.instance.context.getString(
                        R.string.delete_lists_group,
                        list.size
                    )
                )
                deleteDialog.setTip(Utils.instance.getString(R.string.tip_delete_lists_group))
                deleteDialog.setOnDeleteClick { dialog ->
                    deleteLists(list)
                }
                deleteDialog.show()
            } else {
                ToastUtils.showShort(R.string.select_the_tag_group_you_want_to_delete)
            }
        }
    })

    fun getListsGroup() {
        val map = mutableMapOf<String, Any?>()
        map["deviceId"] = mDeviceId
        val body = Gson().toJson(map).toRequestBody(BaseHttp.MEDIA_TYPE_JSON)
        BaseHttp.api.getListsByDeviceId(body)
            .compose(CommonTransformer())
            .subscribe(object : BaseObserver<List<ListsEntity>>() {
                override fun onSubscribe(d: Disposable) {
                    super.onSubscribe(d)
                    showLoading()
                }

                override fun onSuccess(result: List<ListsEntity>?) {
                    super.onSuccess(result)
                    items.clear()
                    result?.forEach {
                        items.add(
                            ListsItemViewModel(
                                this@ListsViewModel,
                                it,
                                isEdit.get() ?: false
                            )
                        )
                    }
                }

                override fun onComplete() {
                    super.onComplete()
                    hideLoading()
                }
            })
    }

    fun deleteLists(data: List<ListsEntity>) {
        val map = mutableMapOf<String, Any?>()
        map["deviceId"] = mDeviceId
        map["listsId"] = data.map { it.id }
        val body = Gson().toJson(map).toRequestBody(BaseHttp.MEDIA_TYPE_JSON)
        BaseHttp.api.deleteListsToId(body)
            .compose(CommonTransformer())
            .subscribe(object : BaseObserver<Boolean>() {
                override fun onSubscribe(d: Disposable) {
                    super.onSubscribe(d)
                    showLoading()
                }

                override fun onSuccess(result: Boolean?) {
                    super.onSuccess(result)
                    if (result == true) {
                        getListsGroup()
                    } else {
                        ToastUtils.showShort(R.string.delete_failed)
                    }
                }

                override fun onError(e: ApiException) {
                    super.onError(e)
                    hideLoading()
                }
            })
    }


    fun bindFrames(code: String) {
        val map = mutableMapOf<String, Any>()
        map["qrcode"] = code
        val json = Gson().toJson(map)
        val body = json.toRequestBody(BaseHttp.MEDIA_TYPE_JSON)
        BaseHttp.api.bindDevice(body)
            .compose(CommonTransformer())
            .subscribe(object : BaseObserver<Boolean>() {
                override fun onSubscribe(d: Disposable) {
                    super.onSubscribe(d)
                    LoadingDialog.getInstance().show()
                }

                override fun onSuccess(result: Boolean?) {
                    super.onSuccess(result)
                    if (result == true) {
                        getFrames()
                    } else {
                        ToastUtils.showShort(R.string.bind_failed)
                        LoadingDialog.getInstance().dismiss()
                    }
                }

                override fun onError(e: ApiException) {
                    super.onError(e)
                    LoadingDialog.getInstance().dismiss()
                }
            })
    }

    fun getFrames() {
        val map = mutableMapOf<String, Any>()
        val json = Gson().toJson(map)
        val body = json.toRequestBody(BaseHttp.MEDIA_TYPE_JSON)
        BaseHttp.api.getUserDeviceList(body)
            .compose(CommonTransformer())
            .subscribe(object : BaseObserver<List<FramesEntity>>() {
                override fun onSuccess(result: List<FramesEntity>?) {
                    super.onSuccess(result)
                    if (result?.isNotEmpty() == true) {
                        FramesDataManager.instance.setData(result)
                        for (i in result.indices) {
                            val e = result[i]
                            val bean = LocalFrameEntity(
                                deviceId = e.id,
                                name = e.name,
                                location = e.roomLocation,
                                online = if (e.online!!) 1 else 0
                            )
                            DBFrames.instance.saveOrUpdate(bean)
                        }
                        Handler(Looper.getMainLooper()).postDelayed({
                            syncToDevice(result)
                        }, 500)
                        RxBus.getDefault().post(EventEntity(EventType.FRESH_DEVICE_LIST))
                    } else {
                        LoadingDialog.getInstance().dismiss()
                    }
                }

                override fun onError(e: ApiException) {
                    super.onError(e)
                    LoadingDialog.getInstance().dismiss()
                }

                override fun onComplete() {
                    super.onComplete()
                    RxBus.getDefault().post(EventEntity(EventType.UPDATE_DEVICE_LIST_COMPLETE))
                }
            })
    }

    fun syncToDevice(devices: List<FramesEntity>) {
        val syncDeviceList = devices.filter { it.id != mDeviceId }
        if (syncDeviceList.isEmpty()) {
            return
        }
        val listsId = items.filter { it.checked.get() == true }
        if (listsId.isEmpty()) {
            return
        }
        val map = mutableMapOf<String, Any>()
        map["listsId"] = listsId.map { it.data.id!! }
        map["deviceId"] = devices.filter { it.id != mDeviceId }.map { it.id }
        val body = Gson().toJson(map).toRequestBody(BaseHttp.MEDIA_TYPE_JSON)
        BaseHttp.api.bindListsToDevice(body)
            .compose(CommonTransformer())
            .subscribe(object : BaseObserver<Boolean>() {
                override fun onSubscribe(d: Disposable) {
                    super.onSubscribe(d)
                    if (!LoadingDialog.getInstance().isShowing()) {
                        LoadingDialog.getInstance().show()
                    }
                }

                override fun onSuccess(result: Boolean?) {
                    super.onSuccess(result)
                    if (result == true) {
                        ToastUtils.showShort(R.string.synchronization_is_successful)
                    } else {
                        ToastUtils.showShort(R.string.synchronization_failed)
                    }
                }

                override fun onComplete() {
                    super.onComplete()
                    LoadingDialog.getInstance().dismiss()
                }
            })
    }
}